package com.xqf.securitydemo.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.xqf.securitydemo.handle.MyAccessDeniedHandler;
import com.xqf.securitydemo.handle.MyAuthenticationFailureHandler;
import com.xqf.securitydemo.handle.MyAuthenticationSuccessHandler;
import com.xqf.securitydemo.service.UserDetailsServiceImpl;
import jdk.nashorn.internal.runtime.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author:祺诺
 * @name:谢钱枫1053557904@qq.com
 * @date:2/12/2021 下午 5:34
 * @poject:Security-Demo
 */
@Configuration

public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;
    //配置自定义验证页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单提交
        http.formLogin()
                //设置账户密码的参数别名
                //实际上只是从请求参数中获取参数放入
                //默认是username 和 password
                //表单请求只能是post
                //要和表单提交的字段相同
                .usernameParameter("username123")
                .passwordParameter("password123")
                //当发现/login时认为是登录 必须和表单提交的地址号是一样的 去执行UserDetailsServiceImpl
                .loginProcessingUrl("/login")
                //自定义登录页面
                .loginPage("/login.html")
                //登陆成功后跳转页面 必须是Post请求
                .successForwardUrl("/toMain")
                //登录成功后的处理器 不能和successForwardUrl共存
                //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                //登陆失败返回 必须是post请求
                .failureForwardUrl("/toError");
                //登录失败后的处理器 不能和failureForwardUrl共存
                //.failureHandler(new MyAuthenticationFailureHandler("/error.html"));


        //开启拦截 授权认证
        http.authorizeRequests()
                //login.html不需要被认证
                .antMatchers("/login.html").permitAll()
                //error.html不需要被验证
                //.antMatchers("/error.html").permitAll()
                //access权限表达式
                .antMatchers("/error.html").access("permitAll()")
                //放行静态资源
                //ant表达式
                .antMatchers("/js/**","/css/**","/images/**").permitAll()
                //可以通过扩展名放行
                //.antMatchers("/**/*.png").permitAll()
                //正则表达式类型的使用
                //.regexMatchers(".+[.]png").permitAll()
                //可以在开始添加请求方式的拦截
                //.regexMatchers(HttpMethod.POST,"/demo").permitAll()
                //.antMatchers(HttpMethod.POST,"login.html").permitAll()
                //.mvcMatchers("/demo").servletPath("/xxxx").permitAll()
                //.antMatchers("/xxxx/demo").permitAll()
                //权限控制
                //.antMatchers("/main1.html").hasAnyAuthority("Admin")
                //角色权限
                //.antMatchers("/main1.html").hasAnyAuthority("admin","Admin")
                //.antMatchers("/main1.html").hasRole("abc")
                //.antMatchers("/main1.html").hasAnyRole("abc,ABC")
                //.antMatchers("/main1.html").access("hasAnyRole('abc,ABC')")
                //ip权限控制
                //.antMatchers("/main1.html").hasIpAddress("127.0.0.1")
                //任何请求都需要登陆之后才能够被访问
                .anyRequest().authenticated();
                //.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

        //关闭csrf防护
        http.csrf().disable();


        //异常处理
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);

        //记住我
        http.rememberMe()
                .userDetailsService(userDetailsService)
                //持久层对象
                .tokenRepository(persistentTokenRepository);
    }

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //自动建表 第一次启动的时候需要 第二次启动的时候需要注释掉
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

}
